import re

keywords = {
             'abs' : 0,
             'add' : 1,
             'aload' : 2,
             'anchorsearch' : 3,
             'and' : 4,
             'arc' : 5,
             'arcn' : 6,
             'arct' : 7,
             'arcto' : 8,
             'array' : 9,
             'ashow' : 10,
             'astore' : 11,
             'awidthshow' : 12,
             'begin' : 13,
             'bind' : 14,
             'bitshift' : 15,
             'ceiling' : 16,
             'charpath' : 17,
             'clear' : 18,
             'cleartomark' : 19,
             'clip' : 20,
             'clippath' : 21,
             'closepath' : 22,
             'concat' : 23,
             'concatmatrix' : 24,
             'copy' : 25,
             'count' : 26,
             'counttomark' : 27,
             'currentcmykcolor' : 28,
             'currentdash' : 29,
             'currentdict' : 30,
             'currentfile' : 31,
             'currentfont' : 32,
             'currentgray' : 33,
             'currentgstate' : 34,
             'currenthsbcolor' : 35,
             'currentlinecap' : 36,
             'currentlinejoin' : 37,
             'currentlinewidth' : 38,
             'currentmatrix' : 39,
             'currentpoint' : 40,
             'currentrgbcolor' : 41,
             'currentshared' : 42,
             'curveto' : 43,
             'cvi' : 44,
             'cvlit' : 45,
             'cvn' : 46,
             'cvr' : 47,
             'cvrs' : 48,
             'cvs' : 49,
             'cvx' : 50,
             'def' : 51,
             'defineusername' : 52,
             'dict' : 53,
             'div' : 54,
             'dtransform' : 55,
             'dup' : 56,
             'end' : 57,
             'eoclip' : 58,
             'eofill' : 59,
             'eoviewclip' : 60,
             'eq' : 61,
             'exch' : 62,
             'exec' : 63,
             'exit' : 64,
             'file' : 65,
             'fill' : 66,
             'findfont' : 67,
             'flattenpath' : 68,
             'floor' : 69,
             'flush' : 70,
             'flushfile' : 71,
             'for' : 72,
             'forall' : 73,
             'ge' : 74,
             'get' : 75,
             'getinterval' : 76,
             'grestore' : 77,
             'gsave' : 78,
             'gstate' : 79,
             'gt' : 80,
             'identmatrix' : 81,
             'idiv' : 82,
             'idtransform' : 83,
             'if' : 84,
             'ifelse' : 85,
             'image' : 86,
             'imagemask' : 87,
             'index' : 88,
             'ineofill' : 89,
             'infill' : 90,
             'initviewclip' : 91,
             'inueofill' : 92,
             'inufill' : 93,
             'invertmatrix' : 94,
             'itransform' : 95,
             'known' : 96,
             'le' : 97,
             'length' : 98,
             'lineto' : 99,
             'load' : 100,
             'loop' : 101,
             'lt' : 102,
             'makefont' : 103,
             'matrix' : 104,
             'maxlength' : 105,
             'mod' : 106,
             'moveto' : 107,
             'mul' : 108,
             'ne' : 109,
             'neg' : 110,
             'newpath' : 111,
             'not' : 112,
             'null' : 113,
             'or' : 114,
             'pathbbox' : 115,
             'pathforall' : 116,
             'pop' : 117,
             'print' : 118,
             'printobject' : 119,
             'put' : 120,
             'putinterval' : 121,
             'rcurveto' : 122,
             'read' : 123,
             'readhexstring' : 124,
             'readline' : 125,
             'readstring' : 126,
             'rectclip' : 127,
             'rectfill' : 128,
             'rectstroke' : 129,
             'rectviewclip' : 130,
             'repeat' : 131,
             'restore' : 132,
             'rlineto' : 133,
             'rmoveto' : 134,
             'roll' : 135,
             'rotate' : 136,
             'round' : 137,
             'save' : 138,
             'scale' : 139,
             'scalefont' : 140,
             'search' : 141,
             'selectfont' : 142,
             'setbbox' : 143,
             'setcachedevice' : 144,
             'setcachedevice2' : 145,
             'setcharwidth' : 146,
             'setcmykcolor' : 147,
             'setdash' : 148,
             'setfont' : 149,
             'setgray' : 150,
             'setgstate' : 151,
             'sethsbcolor' : 152,
             'setlinecap' : 153,
             'setlinejoin' : 154,
             'setlinewidth' : 155,
             'setmatrix' : 156,
             'setrgbcolor' : 157,
             'setshared' : 158,
             'shareddict' : 159,
             'show' : 160,
             'showpage' : 161,
             'stop' : 162,
             'stopped' : 163,
             'store' : 164,
             'string' : 165,
             'stringwidth' : 166,
             'stroke' : 167,
             'strokepath' : 168,
             'sub' : 169,
             'systemdict' : 170,
             'token' : 171,
             'transform' : 172,
             'translate' : 173,
             'truncate' : 174,
             'type' : 175,
             'uappend' : 176,
             'ucache' : 177,
             'ueofill' : 178,
             'ufill' : 179,
             'undef' : 180,
             'upath' : 181,
             'userdict' : 182,
             'ustroke' : 183,
             'viewclip' : 184,
             'viewclippath' : 185,
             'where' : 186,
             'widthshow' : 187,
             'write' : 188,
             'writehexstring' : 189,
             'writeobject' : 190,
             'writestring' : 191,
             'wtranslation' : 192,
             'xor' : 193,
             'xshow' : 194,
             'yshow' : 195,
             'xyshow' : 196,
             'FontDirectory' : 197,
             'SharedFontDirectory' : 198,
             'Courier' : 199,
             'Courier-Bold' : 200,
             'Courier-BoldOblique' : 201,
             'Courier-Oblique' : 202,
             'Helvetica' : 203,
             'Helvetica-Bold' : 204,
             'Helvetica-BoldOblique' : 205,
             'Helvetica-Oblique' : 206,
             'Symbol' : 207,
             'Times-Bold' : 208,
             'Times-BoldItalic' : 209,
             'Times-Italic' : 210,
             'Times-Roman' : 211,
             'execuserobject' : 212,
             'currentcolor' : 213,
             'currentcolorspace' : 214,
             'currentglobal' : 215,
             'execform' : 216,
             'filter' : 217,
             'findresource' : 218,
             'globaldict' : 219,
             'makepattern' : 220,
             'setcolor' : 221,
             'setcolorspace' : 222,
             'setglobal' : 223,
             'setpagedevice' : 224,
             'setpattern' : 225,
           }

base85 = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstu'

keywordChars = '[^ \r\t\n%/()\[\]\{\}<>\x85-\x95]'

def countWhitespace(s): return sum(c in ' \t\n' for c in s)

def chooseBest(choices):
  choices = [x for x in choices if x]
  if len(choices) == 0:
    return None
  if len(choices) == 1:
    return choices[0]

  # Prefer shorter.
  m = min(map(len, choices))
  choices = [x for x in choices if len(x) == m]

  # Prefer more whitespace.
  m = max(map(countWhitespace, choices))
  choices = [x for x in choices if countWhitespace(x) == m]

  # Prefer fewer binary characters.
  m = min(map(count_binary, choices))
  choices = [x for x in choices if count_binary(x) == m]

  # Prefer the first.
  return choices[0]

def count_binary(s):
  return sum(map(is_binary, s))

def is_binary(c):
  return not (c in '\t\n' or (32 <= ord(c) < 127))

def containsBinary(s):
  return any(map(is_binary, s))

def hexEscapeString(s):
  s = ''.join('%02x'%ord(c) for c in s)
  if s[len(s) - 1:] == '0': s = s[:-1]
  return '<%s>' % s

def base85EscapeString(s):
  i = 0
  r = ''
  while i < len(s):
    p = s[i:i+4]
    if p == '\0'*4:
      x = 'z' # Special character for 4 nulls.
    else:
      # TODO: Try appending other characters than nulls.
      pp = p + '\0' * (4 - len(p))
      n = parseBigEndianInteger(pp, False)
      x = ''
      for j in range(5):
        x = base85[n % 85] + x
        n /= 85
      x = x[:len(p)+1]
    r += x
    i += 4
  return '<~%s~' % r

def toOctal(x):
  if x < 8:
    return `x`
  else:
    return toOctal(x/8) + toOctal(x%8)

def escapeString(s):
  """
  Escape '(', ')' and '\' characters, where necessary.
  Convert \r to \n.
  """
  t = ''
  x = s.count(')')
  d = 0
  for c in s:
    if c == ')':
      if d == 0: t += r'\)'
      else: t += ')'; d -= 1
      x -= 1
    elif c == '(':
      if x > d: t += '('; d += 1
      else: t += r'\('
    elif c == '\\': t += r'\\'
    else: t += c

  return t

def translateBinaryCharacters(s):
  result = ''
  for i,c in enumerate(s):
    if not is_binary(c):
      result += c
    elif ord(c) == 8:
      result += r'\b'
    elif ord(c) == 12:
      result += r'\f'
    elif ord(c) == 13:
      result += r'\r'
    else:
      if i != len(s) - 1 and '0' <= s[i+1] <= '7':
        result += '\\%03i' % int(toOctal(ord(c)))
      else:
        result += '\\' + toOctal(ord(c))

  return result

def size_of_integer(i):
  for j in [1, 2, 4]:
    max_int = 1 << (8 * j - 1)
    if i >= -max_int and i < max_int: return j
  raise "Integer out of range: %s" % i

def int_to_string(i, n):
  """Convert an integer to a big endian string of length n."""
  r = ''
  while n:
    r = chr(i & 0xff) + r
    i >>= 8
    n -= 1
  return r

def integerArrayToBinary(a):
  max_size = max(size_of_integer(i) for i in a)

  if max_size < 4: int_size = 2; r = 32
  else: int_size = 4; r = 0

  result = '\x95' + chr(r) + int_to_string(len(a), 2)
  for i in a:
    result += int_to_string(i, int_size)
  return result

def int_to_base36(i):
  if i == 0: return '0'
  if i < 0: i += (1 << 32)
  s = ''
  while i:
    s = '0123456789abcdefghijklmnopqrstuvwxyz'[i % 36] + s
    i /= 36
  return s
    
class ResultBuilder:
  def __init__(self, allowBinary):
    self.prevNeedingSpace = None
    self.prevNotNeedingSpace = ''
    self.allowBinary = allowBinary

  def addPiece(self, piecesNeedingSpace, piecesNotNeedingSpace):
    newNeedingSpace = []
    newNotNeedingSpace = []

    for pieceNeedingSpace in piecesNeedingSpace:
      if not self.prevNeedingSpace is None:
        newNeedingSpace += [self.prevNeedingSpace + ' ' + pieceNeedingSpace]
      if not self.prevNotNeedingSpace is None:
        newNeedingSpace += [self.prevNotNeedingSpace + pieceNeedingSpace]

    for pieceNotNeedingSpace in piecesNotNeedingSpace:
      if not self.allowBinary and containsBinary(pieceNotNeedingSpace):
        continue
      if not self.prevNeedingSpace is None:
        # Special case for two literals following each other: / /
        if self.prevNeedingSpace[-1] == '/' and pieceNotNeedingSpace[0] == '/':
          newNotNeedingSpace += [self.prevNeedingSpace + ' ' + pieceNotNeedingSpace]
        else:
          newNotNeedingSpace += [self.prevNeedingSpace + pieceNotNeedingSpace]
      if not self.prevNotNeedingSpace is None:
        newNotNeedingSpace += [self.prevNotNeedingSpace + pieceNotNeedingSpace]

    self.prevNeedingSpace = chooseBest(newNeedingSpace)
    self.prevNotNeedingSpace = chooseBest(newNotNeedingSpace)

  def getResult(self):
    return chooseBest([self.prevNeedingSpace, self.prevNotNeedingSpace]) or ''

  def handleString(self, s):
    a = []
    if self.allowBinary:
      if not '\r' in s:
        a += ['(' + escapeString(s) + ')']
      if len(s) < 256:
        a += ['\x8e' + chr(len(s)) + s]
      else:
        a += ['\x8f' + chr(len(s) / 256) +
                       chr(len(s) % 256) + s]
    else:
      a += ['(%s)' % translateBinaryCharacters(escapeString(s))]
    a += [hexEscapeString(s)]
    a += [base85EscapeString(s)]
    self.addPiece([], a)

  def handleInteger(self, i):
    base36 = int_to_base36(i)
    no_binary = [str(i), "36#" + base36]

    if 0x80 > i >= -0x80:
      self.addPiece(no_binary, ['\x88' + chr(i & 0xff)])
    elif 0x8000 > i >= -0x8000:
      self.addPiece(no_binary, ['\x87' +
                               chr(i & 0xff) +
                               chr((i >> 8) & 0xff)])
    elif 0x80000000 > i >= -0x80000000:
      self.addPiece(no_binary, ['\x85' +
                               chr(i & 0xff) +
                               chr((i >> 8) & 0xff) +
                               chr((i >> 16) & 0xff) +
                               chr((i >> 24) & 0xff)])
    else:
      raise "Integer out of range: %s" % i

  def handleLiteral(self, literal):
    self.addPiece([], ['/' + literal])
    self.addPiece([''], [])

  def handleMark(self):
    self.addPiece([], ['['])

  def handleBeginDictionary(self):
    self.addPiece([], ['<<'])

  def handleEndDictionary(self):
    self.addPiece([], ['>>'])

  def handleCreateArray(self):
    self.addPiece([], [']'])

  def handleBeginBlock(self):
    self.addPiece([], ['{'])

  def handleEndBlock(self):
    self.addPiece([], ['}'])

  def handleKeyword(self, keyword):
    self.addPiece([keyword], ['\x92' + chr(keywords[keyword])])

  def handleIntegerArray(self, a):
    s = ' '.join(map(str,a))
    no_binary = '{' + convert_unbinary(s) + '}'
    binary = '{' + convert_binary(s) + '}'
    packed = integerArrayToBinary(a)
    self.addPiece([], [packed, binary, no_binary])

  def handleUnknown(self, characters):
    self.addPiece([characters], [])

  def handle(self, token_type, *args):
    getattr(self, 'handle' + token_type)(*args)

class IntegerArrayCollector():
  """Forwards all tokens to another ResultBuilder.
  If a homogeneous array is detected, the tokens to create it are removed
  and replaced with a single homogeneous array token."""
  def __init__(self, result_builder):
    self.result_builder = result_builder
    self.items = None

  def flush(self):
    self.result_builder.handle('BeginBlock')
    for item in self.items:
      self.result_builder.handle('Integer', item)
    self.items = None

  def handle(self, token_type, *args):
    is_handled = False
    if not self.items is None:
      if token_type == 'EndBlock' and len(self.items):
        # Completed a homogeneous array.
        self.result_builder.handle('IntegerArray', self.items)
        self.items = None
        is_handled = True
      elif token_type == 'Integer':
        # Another element in a homogeneous array.
        self.items.append(args[0])
        is_handled = True
      else:
        # Not a homogenous array: forward all the buffered tokens.
        self.flush()

    if not is_handled:
      if token_type == 'BeginBlock':
        # This might start a homogenous array. Buffer tokens until we are sure.
        self.items = []
      else:
        self.result_builder.handle(token_type, *args)

  def getResult(self):
    if not self.items is None:
      self.flush()
    return self.result_builder.getResult()

def parseBigEndianInteger(s, is_signed):
  n = 0
  for c in s: n = n * 256 + ord(c)
  if is_signed and n >= 1 << (8 * len(s) - 1):
    n -= 1 << (8 * len(s))
  return n

def parseLittleEndianInteger(s, is_signed):
  return parseBigEndianInteger(s[::-1], is_signed)

def parseRadixInteger(s):
  """Parse a number of the form rr#ddddd, such as 16#ff."""
  if not re.match(r'\d\d?#[0-9A-Za-z]+', s): return None
  radix, digits = s.split('#')
  radix = int(radix)
  if radix < 2 or radix > 36: return None
  result = int(digits, radix)
  if result >= (1 << 32): return None
  if result >= (1 << 31): result -= (1 << 32)
  return result
  
def parse(text, rb):
  """ Parse a PostScript program and reformat it.
  text: PostScript program to parse.
  rb: Result builder."""

  indent = 0
  index = 0
  while index < len(text):
    char = text[index]

    if char in ' \t\r\n':
      index += 1

    elif char == '/':
      m = re.match('/' + keywordChars + '*', text[index:])
      matchString = m.group(0)
      rb.handle('Literal', matchString[1:])
      index += len(matchString)

    elif char == '{':
      rb.handle('BeginBlock')
      index += 1

    elif char in '}':
      rb.handle('EndBlock')
      index += 1

    elif char == '[':
      rb.handle('Mark')
      index += 1

    elif char == ']':
      rb.handle('CreateArray')
      index += 1

    elif char == '(':
      depth = 1
      j = index + 1
      s = ''
      while depth:
        if j >= len(text):
          raise 'Syntax error: Unmatched ('
        if text[j] == '\\':
          j += 1
          if text[j] == 'b':
            s += chr(8)
          elif text[j] == 'f':
            s += chr(12)
          elif text[j] == 'n':
            s += chr(10)
          elif text[j] == 'r':
            s += chr(13)
          elif text[j] == 't':
            s += chr(9)
          elif '0' <= text[j] <= '7':
            i = 0
            for k in range(3):
              i = i * 8 + int(text[j])
              j += 1
              if j == len(text): break
              if not '0' <= text[j] <= '7': break
            j -= 1
            s += chr(i & 0xff)
          else:
            s += text[j]
        else:
          if text[j] == '(':
            s += text[j]
            depth += 1
          elif text[j] == ')':
            depth -= 1
            if depth:
               s += text[j]
          elif text[j] == '\r': s += '\n' # \r is converted to \n!
          else: s += text[j]
        j += 1
      rb.handle('String', s)
      index = j

    elif char == ')':
      raise 'Syntax error: Unmatched )'

    elif char == '<':
      if index + 1 < len(text) and text[index + 1] == '<':
        rb.handle('BeginDictionary')
        index += 2

      elif index + 1 < len(text) and text[index + 1] == '~':
        # Base 85 string.
        # Extract the characters.
        i = index + 2
        r = ''
        while i < len(text):
          if text[i] in ' \n\t\0\x0c':
            i += 1
          elif text[i] in base85 + 'z':
            r += text[i]
            i += 1
          elif text[i] == '~':
            i += 1
            if i < len(text) and text[i] == '>':
              i += 1
            break
          else:
            raise 'Invalid base 85 string.'
        index = i

        # Convert from base 85.
        s = ''
        i = 0
        while i < len(r):
          if r[i] == 'z':
            s += '\0' * 4
            i += 1
          else:
            p = r[i:i+5]
            if len(p) == 1:
              raise 'Unexpected end of base 85 string.'
            n = 0
            for c in (p + '!!!')[:5]:
              n = n * 85 + base85.index(c)
            s += int_to_string(n, 4)[:len(p) - 1]
            i += 5
        rb.handleString(s)

      else:
        # Hexadecimal encoded string
        j = index
        r = ''
        d = 0
        firstChar = True
        while True:
          j += 1
          if j == len(text):
            raise 'Syntax error: unmatched <'
          c = text[j].lower()
          if c == '>':
             break
          if c in ' \n\t':
             continue
          if c not in '0123456789abcdef':
            raise 'Invalid hex character: %02x' % ord(c)
          d = d * 16 + ord(c) - [ord('a') - 10, ord('0')][c < 'a']
          if not firstChar:
            r += chr(d)
            d = 0
          firstChar = not firstChar
        if not firstChar:
          r += chr(d * 16)
        rb.handle('String', r)
        index = j + 1

    elif char == '>':
      if index + 1 < len(text) and text[index + 1] == '>':
        rb.handle('EndDictionary')
        index += 2
      else:
        raise 'Syntax error: unmatched >'

    elif char == '%':
      while text[index] != '\n':
        index += 1
        if index == len(text): break

    elif char == '\x84':
      # Integer constant - Big Endian (4 bytes)
      index += 1
      if index + 4 > len(text):
        raise 'Unexpected end of file in 4 byte integer.'
      i = parseBigEndianInteger(text[index: index + 4], True)
      rb.handle('Integer', i)
      index += 4

    elif char == '\x85':
      # Integer constant - Little Endian (4 bytes)
      index += 1
      if index + 4 > len(text):
        raise 'Unexpected end of file in 4 byte integer.'
      i = parseLittleEndianInteger(text[index: index + 4], True)
      rb.handle('Integer', i)
      index += 4

    elif char == '\x86':
      # Integer constant - Big endian (2 bytes)
      index += 1
      if index + 2 > len(text):
        raise 'Unexpected end of file in 2 byte integer.'
      i = parseBigEndianInteger(text[index: index + 2], True)
      rb.handle('Integer', i)
      index += 2

    elif char == '\x87':
      # Integer constant - Little endian (2 bytes)
      index += 1
      if index + 2 > len(text):
        raise 'Unexpected end of file in 2 byte integer.'
      i = parseLittleEndianInteger(text[index: index + 2], True)
      rb.handle('Integer', i)
      index += 2

    elif char == '\x88':
      # Integer constant (1 byte)
      index += 1
      if index + 1 > len(text):
        raise 'Unexpected end of file in 1 byte integer.'
      i = parseLittleEndianInteger(text[index], True)
      rb.handle('Integer', i)
      index += 1

    elif char == '\x89': raise "Fixed point number not implemented yet."
    elif char == '\x8a': raise "IEEE real (big endian)  not implemented yet."
    elif char == '\x8b': raise "IEEE real (little endian)  not implemented yet."
    elif char == '\x8c': raise "Native real not implemented yet."
    elif char == '\x8d': raise "Boolean not implemented yet."

    elif char == '\x8e':
      # String.
      # TODO: Check length.
      length = ord(text[index + 1])
      s = text[index + 2:index + 2 + length]
      rb.handle('String', s)
      index += length + 2

    elif char == '\x8f':
      # Long string (length: big endian).
      # TODO: Check length.
      length = parseBigEndianInteger(text[index + 1: index + 3], False)
      s = text[index + 3:index + 3 + length]
      rb.handle('String', s)
      index += length + 3

    elif char == '\x90':
      # Long string (length: big endian).
      # TODO: Check length.
      length = parseLittleEndianInteger(text[index + 1: index + 3], False)
      s = text[index + 3:index + 3 + length]
      rb.handle('String', s)
      index += length + 3

    elif char == '\x91' or char == '\x92':
      keywordCode = ord(text[index + 1])
      if not keywordCode in keywords.itervalues():
        raise 'Unknown keyword: %s (%02x)' % (keywordCode, keywordCode)
      for k,v in keywords.iteritems():
        if v == keywordCode:
          keyword = k
          break
      if char == '\x91': t = 'Literal'
      else: t = 'Keyword'
      rb.handle(t, keyword)
      index += 2

    elif char == '\x92': raise "Reserved binary token."
    elif char == '\x93': raise "Reserved."

    elif char == '\x95':
      # Homogeneous array.

      if index + 4 > len(text):
        raise "Syntax error: Unexpected end of file in homogeneous array."

      # Read the representation.
      r = ord(text[index + 1])
      if not r in [0, 32, 128, 160]:
        raise "Homogeneous array of non-integers not implemented."
      big_endian = r < 128
      if not big_endian: r -= 128
      parser = [parseLittleEndianInteger,
                parseBigEndianInteger][big_endian]
      if r == 0 : elementLength = 4
      else: elementLength = 2

      # Read the array length.
      arrayLength = parser(text[index + 2: index + 4], False)

      index += 4

      # Parse the elements of the array.
      a = []
      for i in range(arrayLength):
        if index + elementLength > len(text):
          raise "Syntax error: Unexpected end of file in homogeneous array."

        a.append(parser(text[index: index + elementLength], True))
        index += elementLength
        
      rb.handle('IntegerArray', a)

    elif char >= '\x96' and char < '\xa0': raise "Unassigned binary token."

    else:
      m = re.match(keywordChars + '+', text[index:])
      matchString = m.group(0)
      if matchString in keywords:
        rb.handle('Keyword', matchString)
      else:
        is_handled = False

        # Test for a simple base 10 integer.
        if re.match(r'-?\d+$', matchString):
          i = int(matchString)
          rb.handle('Integer', i)
          is_handled = True

        # Test for an integer with a radix.
        if not is_handled:
          i = parseRadixInteger(matchString)
          if not i is None:
            rb.handle('Integer', i)         
            is_handled = True

        # Unknown.
        if not is_handled:
          rb.handle('Unknown', matchString)

      index += len(matchString)

  return rb.getResult()

def convert_binary(text):
  return parse(text, IntegerArrayCollector(ResultBuilder(True)))

def convert_unbinary(text):
  return parse(text, ResultBuilder(False))

def main():
  import sys
  text = sys.stdin.read()
  allow_binary = len(sys.argv) == 1
  if allow_binary:
    result = convert_binary(text)
  else:
    result = convert_unbinary(text)
  sys.stdout.write(result)

if __name__=='__main__':
  main()
